Skip to content

Conversation

arash-mosavi
Copy link

@arash-mosavi arash-mosavi commented Sep 27, 2025

Summary

Prevent a slice out-of-range panic in the LSP when computing completions/auto-imports for edge-case positions or empty symbol names.
The change adds minimal bounds checks and early returns around string/slice indexing in the language server hot paths.

Fixes #1691.

Repro (one-liner)

Typing at boundary positions (e.g., before the first char, at len(text), or on an empty/whitespace symbol) could lead to computing invalid indices and slicing out of range, causing a panic in completions/auto-imports.

Root Cause

Helpers assumed valid non-empty symbols and in-range positions, then immediately sliced the source text or accessed s[0]. For empty names or out-of-bounds positions, indices became negative or > len, triggering a panic.

What’s changed (small & localized)

  • internal/ls/completions.go
    • Clamp indices in getWordLengthAndStart / getDotAccessor before slicing.
    • Early-return a safe default when start >= end or symbol is empty.
  • internal/ls/autoimports.go
    • Validate slice bounds when deriving node_modules subpaths; avoid constructing invalid substrings at boundaries.
  • internal/ls/autoimportsexportinfo.go
    • Skip empty symbol names before accessing the first character.

Changes are narrowly scoped to the points where invalid indices were observed; no refactors or logic rewrites.

Behavior & Compatibility

  • Only change is no more panics in these edge cases.
  • For invalid input (empty symbol / OOB position) we return a safe default so the LSP remains responsive.
  • Performance impact is negligible (constant-time checks on hot paths).

Tests

  • Manually verified with boundary positions (-1, len(text), len(text)+1) and empty/whitespace symbols.
  • Happy-path completions/auto-imports unchanged.
  • (Can follow up with regression tests for these cases if desired.)

Risk

Low. Defensive bounds checks and early returns only; no broader behavior changes.

Notes for maintainers

This PR comes from a fork; could you please Approve and run the workflows so required checks can report?
All local checks pass (go test ./..., also with -race).

@Copilot Copilot AI review requested due to automatic review settings September 27, 2025 09:15
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds bounds checking to prevent slice bounds out of range panics in the language server code. The changes add defensive programming measures to safely handle edge cases where positions or indices might be out of bounds when slicing strings or arrays.

  • Added bounds checks before slicing source file text with position parameters
  • Added validation for empty symbol names before accessing first character
  • Added comprehensive bounds checking for node modules path slicing operations

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
internal/ls/completions.go Added bounds checks before slicing source file text in getWordLengthAndStart and getDotAccessor functions
internal/ls/autoimportsexportinfo.go Added empty string check before accessing first character of symbol name
internal/ls/autoimports.go Added comprehensive bounds checking for node modules path slicing operations and fixed missing closing brace

@arash-mosavi arash-mosavi changed the title fix: add bounds checks to prevent slice bounds out of range panic lsp: prevent out-of-range panic in autoimports/completions when symbol name or position is invalid (fixes #1691) Sep 27, 2025
@arash-mosavi
Copy link
Author

@microsoft-github-policy-service agree

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

arash-mosavi and others added 2 commits September 30, 2025 15:48
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Member

@iisaduan iisaduan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The additions to autoimports look good, but I don't think the completions checks are necessary.

arash-mosavi and others added 5 commits October 1, 2025 07:50
- Add bounds check before accessing names[0] when symbol names array may be empty
- Add bounds checking in getNodeModuleRootSpecifier for component array access
- Prevent panics when accessing array elements without verifying length

Fixes microsoft#1691

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
The exportInfoId counter was being read but never incremented, causing
all export info entries to receive the same ID (1). When multiple
goroutines called add() concurrently, they would all write to the same
map entry (e.symbols[1]), creating a data race.

This fix properly increments the counter after adding each entry,
ensuring unique IDs and eliminating the race condition.
@arash-mosavi arash-mosavi requested a review from iisaduan October 1, 2025 06:07
@arash-mosavi arash-mosavi requested a review from Copilot October 1, 2025 06:41
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

arash-mosavi and others added 2 commits October 2, 2025 08:33
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@arash-mosavi arash-mosavi requested a review from Copilot October 2, 2025 05:03
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

internal/ls/autoimports.go:1326

  • Extra closing brace added that doesn't match any opening brace in the getNodeModuleRootSpecifier function. This will cause a compilation error.
	return ""
}

@arash-mosavi arash-mosavi requested a review from Copilot October 4, 2025 17:45
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.


// Bounds check to prevent slice bounds out of range panic
fileName := moduleFile.FileName()
if topLevelPackageNameIndex+1 >= 0 && packageRootIndex >= 0 && topLevelPackageNameIndex+1 <= packageRootIndex && packageRootIndex <= len(fileName) {
Copy link
Preview

Copilot AI Oct 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The bounds checking condition is complex and hard to read. Consider extracting this logic into a helper function like isValidSliceRange(start, end, length int) bool to improve readability and maintainability.

Copilot uses AI. Check for mistakes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[lsp] panic with slice bounds out of range [:-1] when typing anything in a source file
2 participants